#define SOKOL_IMPL
#ifndef __USE_EGL_TRUE_
#define SOKOL_GLCORE
#else
#define SOKOL_GLES3
#endif

#include "sokol_app.h"
#include "sokol_gfx.h"
#include "sokol_glue.h"
#include "sokol_log.h"

static struct {
    sg_pipeline pip;
    sg_bindings bind;
    sg_pass_action pass_action;
} state;

void init(void) {
    sg_setup(&(sg_desc){
        .environment = sglue_environment(),
        .logger.func = slog_func
    });

    float vertices[] = {
        // positions            // colors
        0.0f,  0.5f, 0.5f,     1.0f, 0.0f, 0.0f, 1.0f,
        0.5f, -0.5f, 0.5f,     0.0f, 1.0f, 0.0f, 1.0f,
        -0.5f, -0.5f, 0.5f,     0.0f, 0.0f, 1.0f, 1.0f
    };

    state.bind.vertex_buffers[0] = sg_make_buffer(&(sg_buffer_desc){
        .data = SG_RANGE(vertices),
        .label = "triangle-vertices"
    });

    sg_shader shd = sg_make_shader(&(sg_shader_desc){
        .vertex_func.source = 
#ifndef __USE_EGL_TRUE_
            "#version 410\n"
#else
            "#version 300 es\n"
#endif
            "layout(location=0) in mediump vec4 position;\n"
            "layout(location=1) in mediump vec4 color0;\n"
            "out mediump vec4 color;\n"
            "void main() {\n"
            "  gl_Position = position;\n"
            "  color = color0;\n"
            "}\n",
        .fragment_func.source = 
#ifndef __USE_EGL_TRUE_
            "#version 410\n"
#else
            "#version 300 es\n"
#endif
            "in mediump vec4 color;\n"
            "out mediump vec4 frag_color;\n"
            "void main() {\n"
            "  frag_color = color;\n"
            "}\n"
    });

    state.pip = sg_make_pipeline(&(sg_pipeline_desc){
        .shader = shd,
        .layout = {
            .attrs = {
                [0].format = SG_VERTEXFORMAT_FLOAT3,
                [1].format = SG_VERTEXFORMAT_FLOAT4
            }
        },
        .label = "triangle-pipeline"
    });

    state.pass_action = (sg_pass_action){
        .colors[0] = {
            .load_action=SG_LOADACTION_CLEAR,
            .clear_value={0.0f,0.0f,0.0f,1.0f}
        }
    };
}

void frame(void){
    sg_begin_pass(&(sg_pass){
        .action = state.pass_action,
        .swapchain = sglue_swapchain()
    });

    sg_apply_pipeline(state.pip);
    sg_apply_bindings(&state.bind);
    sg_draw(0, 3, 1);
    sg_end_pass();
    sg_commit();
}

void cleanup(void){
    sg_shutdown();
}

sapp_desc sokol_main(int argc,char **argv){
    (void)argc;(void)argv;
    return (sapp_desc){
        .init_cb = init,
        .frame_cb = frame,
        .cleanup_cb = cleanup,
        .width = 800,
        .height = 600,
        .window_title = "SOKOL_TEST",
        .icon.sokol_default = true,
        .logger.func = slog_func
    };
}